﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ErrataParser
{
    public partial class ErrataParserForm : Form
    {
        private List<HFError> errata;
        private ErrataParser errataParser;

        public ErrataParserForm()
        {
            
            InitializeErrata();
            InitializeComponent();
            InitializeControls();
        }

        private void InitializeErrata()
        {
            errataParser = new ErrataParser();
            errataParser.LoadErrataLists();
            errata = errataParser.GetListOfHFErrors();
        }

        private void InitializeControls()
        {
            sortBy.SelectedIndex = 0;   //sets the default selection to sorting by page number
            foreach (ErrorType errorType in Enum.GetValues(typeof(ErrorType)))
            {
                errorTypesToInclude.Items.Add(HFError.PrettyPrintErrorType(errorType), true);
            }

            foreach(ErrorExtent errorExtent in Enum.GetValues(typeof(ErrorExtent)))
            {
                errorExtentsToInclude.Items.Add(HFError.PrettyPrintErrorExtent(errorExtent), true);
            }

            saveErrataButton.Enabled = false;
            sendToClipboardButton.Enabled = false;
            errataDisplayer.AppendText(
                "Choose the filtering options you desire using the controls to right, and then click the \"Display Matching Errata\" button to begin!");
            errataDisplayer.AppendText(
                "\r\n\r\nKnown issue: the errata parser cannot currently deal with roman numeraled page numbers, and so all errors before the beginning of Chapter 1 are ignored. Note that all such errors seem to be minor language or formatting changes.");
        }

        private void PrintErrata(IEnumerable<HFError> errataToPrint)
        {
            int numErrorsDisplayed = 0;
            errataDisplayer.Clear();
            errataDisplayer.AppendText("Filtered Errata for Head First C#\r\n*********************************\r\nGenerated by the Head First C# Errata Parser/Displayer.\r\nSee http://code.google.com/p/hfcserrataparser/ for current version.\r\nOriginal errata/corrections are copyright O'Reilly and can be found\r\nat http://oreilly.com/catalog/9780596514822/errata/.\r\n*******************************************************************\r\n\r\n");

            foreach (var error in errataToPrint)
            {
                errataDisplayer.AppendText("***********\r\n");
                errataDisplayer.AppendText(error.ToString());
                errataDisplayer.AppendText("\r\n");
                numErrorsDisplayed++;
                displayingCounter.Text = string.Format("Currently displaying {0} errors", numErrorsDisplayed);
                displayingCounter.Refresh();
            }
            
            
        }

        private IEnumerable<HFError> GetFilteredFrom(IEnumerable<HFError> errataToFilter)
        {
            var errataToReturn = (sortBy.SelectedIndex != 1)
                                    ? from error in errataToFilter
                                      where MatchesSelectedFilters(error)
                                      orderby   error.PageNumber,
                                                (int)error.Type
                                      select error
                                    : from error in errataToFilter
                                      where MatchesSelectedFilters(error)
                                      orderby   (int)error.Type,
                                                error.PageNumber
                                      select error;
            return errataToReturn.AsEnumerable();
        }
        
        private bool MatchesSelectedFilters(HFError errorToCheck)
        {
            for (int errorTypeIndex = 0; errorTypeIndex < errorTypesToInclude.Items.Count; errorTypeIndex++)
            {
                if (!errorTypesToInclude.GetItemChecked(errorTypeIndex) &&
                    errorToCheck.Type == (ErrorType) errorTypeIndex)
                    return false;
            }

            for (int errorExtentIndex = 0; errorExtentIndex < errorExtentsToInclude.Items.Count; errorExtentIndex++)
            {
                if (!errorExtentsToInclude.GetItemChecked(errorExtentIndex) &&
                    errorToCheck.Extent == (ErrorExtent) errorExtentIndex)
                    return false;
            }

            if (errorToCheck.PageNumber < fromPageNum.Value || errorToCheck.PageNumber > toPageNum.Value)
                return false;

            return true;
        }

        private void displayErrata_Click(object sender, EventArgs e)
        {
            PrintErrata(GetFilteredFrom(errata));
            if (string.IsNullOrEmpty(errataDisplayer.Text))
                return;
            saveErrataButton.Enabled = true;
            sendToClipboardButton.Enabled = true;
        }

        private void sendToClipboardButton_Click(object sender, EventArgs e)
        {
            errataDisplayer.SelectAll();
            errataDisplayer.Copy();
        }

        private void saveErrataButton_Click(object sender, EventArgs e)
        {
            if(saveErrataDialog.ShowDialog()==DialogResult.OK)
            {
                File.WriteAllText(saveErrataDialog.FileName, errataDisplayer.Text);
            }
        }


    }
}
